package com.sjsu.aws.groupmembership;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.amazonaws.services.dynamodb.model.AttributeValue;
import com.amazonaws.services.dynamodb.model.ComparisonOperator;
import com.amazonaws.services.dynamodb.model.Condition;
import com.amazonaws.services.dynamodb.model.ScanResult;
import com.sjsu.aws.db.QueryCriteria;
import com.sjsu.aws.db.TableOperationImpl;
import com.sjsu.aws.db.TableRow;
import com.sjsu.aws.ephermeralnode.EphemeralServiceImpl;

/**
 * 
 * @author Deepali Pawar
 * 
 */
public class GroupMembershipServiceImpl implements GroupMembershipService {
	
	private final static Logger	LOG	= Logger.getLogger(GroupMembershipServiceImpl.class);
	
	private TableOperationImpl	        tableOperationImpl;
	private EphemeralServiceImpl	    ephemeralServiceImpl;
	private TableRow	                tableRow;
	private QueryCriteria	            criteria;
	
	public GroupMembershipServiceImpl() throws Exception {
		this.tableOperationImpl = new TableOperationImpl();
		this.ephemeralServiceImpl = new EphemeralServiceImpl();
		this.tableRow = new TableRow();
		this.criteria = new QueryCriteria();
	}
	
	@Override
	public void joinGroup(GroupMemberShip g) throws Exception {
		LOG.info("Join Group Membership");
		tableRow.setItem(createGroupMemberShipItem(g));
		tableOperationImpl.insertItem(GroupMembershipConstants.GROUP_TABLE,
		        tableRow);
	}
	
	@Override
	public void disjoinGroup(GroupMemberShip g) throws Exception {
		HashMap<String, Condition> scanFilter = new HashMap<String, Condition>();
		Condition condition1 = new Condition().withComparisonOperator(
		        ComparisonOperator.EQ.toString()).withAttributeValueList(
		        new AttributeValue().withS(g.getGroupId()));
		
		scanFilter.put(GroupMembershipConstants.COLUMN_GROUP_ID, condition1);
		criteria.setScanFilter(scanFilter);
		
		Condition condition = new Condition().withComparisonOperator(
		        ComparisonOperator.EQ.toString()).withAttributeValueList(
		        new AttributeValue().withS(g.getMemberId()));
		
		scanFilter.put(GroupMembershipConstants.COLUMN_MEMBER_ID, condition);
		criteria.setScanFilter(scanFilter);
		
		String uuid = null;
		ScanResult scanResult = tableOperationImpl.queryTable(
		        GroupMembershipConstants.GROUP_TABLE, criteria);
		LOG.info("Read Config" + scanResult.getCount());
		
		for (int i = 0; i < scanResult.getCount(); i++) {
			HashMap<String, AttributeValue> item = (HashMap<String, AttributeValue>) scanResult
			        .getItems().get(i);
			if (item.get(GroupMembershipConstants.COLUMN_MEMBER_ID).getS() != null) {
				uuid = item.get(GroupMembershipConstants.COLUMN_UUID_ID).getS();
				LOG.info("UUID value is "
				        + item.get(GroupMembershipConstants.COLUMN_UUID_ID)
				                .getS());
				tableRow.setDeleteKey(uuid);
				tableOperationImpl.deleteItem(
				        GroupMembershipConstants.GROUP_TABLE, tableRow);
			}
		}
	}
	
	@Override
	public void deleteGroup(GroupMemberShip g) throws Exception {
		HashMap<String, Condition> scanFilter = new HashMap<String, Condition>();
		Condition condition1 = new Condition().withComparisonOperator(
		        ComparisonOperator.EQ.toString()).withAttributeValueList(
		        new AttributeValue().withS(g.getGroupId()));
		
		scanFilter.put(GroupMembershipConstants.COLUMN_GROUP_ID, condition1);
		criteria.setScanFilter(scanFilter);
		
		ScanResult scanResult = tableOperationImpl.queryTable(
		        GroupMembershipConstants.GROUP_TABLE, criteria);
		LOG.info("Read Config" + scanResult.getCount());
		String uuid = null;
		
		for (int i = 0; i < scanResult.getCount(); i++) {
			HashMap<String, AttributeValue> item = (HashMap<String, AttributeValue>) scanResult
			        .getItems().get(i);
			if (item.get(GroupMembershipConstants.COLUMN_MEMBER_ID).getS() != null) {
				uuid = item.get(GroupMembershipConstants.COLUMN_UUID_ID).getS();
				LOG.info("UUID value is "
				        + item.get(GroupMembershipConstants.COLUMN_UUID_ID)
				                .getS());
				tableRow.setDeleteKey(uuid);
				tableOperationImpl.deleteItem(
				        GroupMembershipConstants.GROUP_TABLE, tableRow);
			}
		}
	}
	
	@Override
	public List<GroupMemberShip> listGroupMembers() throws Exception {
		List<GroupMemberShip> groupMemberShipList = new ArrayList<GroupMemberShip>();
		ScanResult scanResult = tableOperationImpl
		        .queryTableWithNoCondition(GroupMembershipConstants.GROUP_TABLE);
		
		for (int i = 0; i < scanResult.getCount(); i++) {
			HashMap<String, AttributeValue> item = (HashMap<String, AttributeValue>) scanResult
			        .getItems().get(i);
			if (item.get(GroupMembershipConstants.COLUMN_UUID_ID).getS() != null) {
				GroupMemberShip groupMemberShip = new GroupMemberShip();
				groupMemberShip.setMemberId(item.get(
				        GroupMembershipConstants.COLUMN_MEMBER_ID).getS());
				groupMemberShipList.add(groupMemberShip);
				
			}
		}
		return groupMemberShipList;
	}
	
	public Map<String, AttributeValue> createGroupMemberShipItem(
	        GroupMemberShip g) throws Exception {
		Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
		item.put(GroupMembershipConstants.COLUMN_UUID_ID,
		        new AttributeValue(g.getUuid()));
		item.put(GroupMembershipConstants.COLUMN_GROUP_ID,
		        new AttributeValue(g.getGroupId()));
		item.put(GroupMembershipConstants.COLUMN_MEMBER_ID, new AttributeValue(
		        g.getMemberId()));
		item.put(GroupMembershipConstants.COLUMN_END_TIMESTAMP,
		        new AttributeValue().withN(String.valueOf(g.getEndTimestamp())));
		return item;
	}
	
	@Override
	public void deleteEphemeralNodesOnDisconnect() throws Exception {
		ephemeralServiceImpl.deleteEphemeralNodesOnDisconnect(
		        GroupMembershipConstants.GROUP_TABLE,
		        GroupMembershipConstants.COLUMN_UUID_ID,
		        GroupMembershipConstants.COLUMN_MEMBER_ID);
	}
	
	@Override
	public void renewEphemeralMembership(GroupMemberShip g) throws Exception {
		ephemeralServiceImpl.renewEphemeralMembership(
		        GroupMembershipConstants.GROUP_TABLE,
		        GroupMembershipConstants.COLUMN_UUID_ID,
		        GroupMembershipConstants.COLUMN_END_TIMESTAMP,
		        GroupMembershipConstants.COLUMN_MEMBER_ID, g.getMemberId(),
		        g.getEndTimestamp());
	}
	
	@Override
	public void deleteTimeOutSessionsForEphemeralNode() throws Exception {
		ephemeralServiceImpl.deleteTimeOutSessionsForEphemeralNode(
		        GroupMembershipConstants.GROUP_TABLE,
		        GroupMembershipConstants.COLUMN_UUID_ID,
		        GroupMembershipConstants.COLUMN_END_TIMESTAMP);
	}
}
